// free tools for java
Simple
T o o l s
-Assembler
--Package examples
---Simple
---Loops
---Mini arithmetic compiler
  This program generates a simple class that does absolutely nothing besides getting initialized. There are basically two things you need to do to make a class file, specify the hierarchy where the class belongs, and write the methods for the class.
ClassEnv nclass = new ClassEnv();
nclass.setClass(new ClassCP("out"));
nclass.setSuperClass
  (new ClassCP("java/lang/Object"));
ClassEnv is the container class that is used to store information about the contents of a class. As various pieces of a class become available, they are added through the methods available in this class. ClassCP is a cpe item. A cpe item is what I call an entry in the constant pool.

The constant pool is like a symbol table for class files, and entries in the constant pool can be of several types, one of which is a ClassCP type. Several classes are provided to create cpe items of various types. The setClass method in ClassEnv sets the class to be the name specified in the associated CP item.

In general, most jas package methods only expect you to provide a cpe, leaving any type checking of the cpe itself to the VM implementation. Correct VM implementations should generate errors if you pass cpe items of the wrong type, but the assembler itself does no such checking.

setSuperClass is another method in ClassEnv that defines the superclass for this class. It too, expects to find a cpe item as its only argument. So the above snippet of code simply creates a new ClassEnv, setting its name to be "out" and defining it to be sub classed from "java/lang/Object".

You can keep creating new CP items and adding them to the ClassEnv. The package will internally "uniquefy" CP items, so at the end only one unique copy will be generated in the class file. You can reuse CP items too, if you wish. Its sometimes just more convenient to create them on the fly instead of carting them with you all the time.

The second step is defining the methods in the class. We will define only one method, the initializer for the class, and just make it call the constructor of its super class. We'll divide this into two steps, first creating the code for the method, and then specifying the access to the method and arguments, etc.

CodeAttr init = new CodeAttr();
init.addInsn(new Insn(opc_aload_0));
init.addInsn
 (new Insn(opc_invokenonvirtual,
           new MethodCP
            ("java/lang/Object",
             "<init>", "()V")));
init.addInsn(new Insn(opc_return));
CodeAttr is a class that represents the body of a method. Once you create a CodeAttr, its addInsn method allows you to append an instruction to the current body. Other methods exist to add a catch table to the body to handle exceptions.

Instances of an instruction are created from the Insn class, or some subclass of Insn. Some instructions, like invokenonvirtual, take cpe's as arguments. For such instructions, the appropriate Insn constructor is used to generate an instance of the instruction.

The second step in defining methods is to specify arguments and access control to the method.
nclass.addMethod
  ((short)ACC_PUBLIC,
   "<init>", "()V", init, null);
The addMethod function allows a code body to be added to a class. At this point, the code to generate the bytecode is ready to be generated, and the entire program looks like this.
import jas.*;
import java.io.*;

//
// This is program that makes calls into the
// jas package to generate a class that does
// nothing at all.

class simple implements RuntimeConstants
{
  public static void main(String argv[])
    throws jasError, IOException
  {

// CodeAttr's contain the body of
// a method.

    CodeAttr init = new CodeAttr();
    init.addInsn(new Insn(opc_aload_0));
    init.addInsn
     (new Insn(opc_invokenonvirtual,
               new MethodCP
                ("java/lang/Object",
                 "<init>", "()V")));
    init.addInsn(new Insn(opc_return));

// ClassEnv's are used as a container
// to hold all information about a class.

    ClassEnv nclass = new ClassEnv();
    nclass.setClass(new ClassCP("out"));
    nclass.setSuperClass
     (new ClassCP("java/lang/Object"));

// Add the init code to the class.
    nclass.addMethod
      ((short)ACC_PUBLIC,
       "<init>", "()V", init, null);

// write it all out
    nclass.write
      (new DataOutputStream
       (new FileOutputStream("out.class")));
  }
}
First compile the code. This example is provided with the distribution, and this sequence shows how it is compiled and run from the distribution root directory.

% javac -g -d . examples/simple.java
% java simple
At this point, the bytecode should have been created, and we can disassemble it to see what it looks like.
% ls -l out.class
-rw-r--r--  1 kbs           118 Dec 31 11:21 out.class
% javap -c -p out
class out extends java.lang.Object {
    public out();
 
Method out()
   0 aload_0
   1 invokenonvirtual #7 <Method java.lang.Object.<init>()V>
   4 return
 
}
% javap -verify out
Class out succeeds
You should always run the verifier after generating bytecode. By default, the verifier is not run when loading files locally, so errors in the bytecode will cause the VM to die.
 
T o o l s/Assembler/Package examples

Simple | Loops | Mini arithmetic compiler

http://www.sbktech.org/jas-java-simple.html Revised: Fri Apr 4 08:31:22 1997
Copyright (C) 1996 KB Sriram.
Comments, bug reports: kbs@sbktech.org
Found something useful?